package com.taoz.mianshiwa.helper;

import com.taoz.mianshiwa.common.ErrorCode;
import com.taoz.mianshiwa.exception.ThrowUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.formula.functions.T;
import org.redisson.api.RScript;
import org.redisson.api.RedissonClient;
import org.redisson.client.codec.IntegerCodec;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.Instant;
import java.util.Collections;
import java.util.concurrent.TimeUnit;

/**
 * 分布式频率统计
 */
@Slf4j
@Service
public class CounterHelper {

    @Resource
    private RedissonClient redissonClient;

    /**
     * 统计当前所在60s的次数
     * @param key
     * @return
     */
    public long incrAndGet(String key) {
        return incrAndGet(key, 60, TimeUnit.SECONDS);
    }

    /**
     * 统计一定时间区间的次数
     * @param key
     * @param interval
     * @param timeUnit
     * @return
     */
    public long incrAndGet(String key, long interval, TimeUnit timeUnit) {
        long expireTime = timeUnit.toSeconds(interval);
        return incrAndGet(key, interval, timeUnit, expireTime);
    }

    public long incrAndGet(String key, long interval, TimeUnit timeUnit, long expireTime) {
        if (key == null) {
            return -1;
        }

        // 后缀时间key
        String redisKey = key + ":" + Instant.now().getEpochSecond() / timeUnit.toSeconds(interval);

        // 求完参数后发送lua脚本执行命令

        // 得到一个可以发送lua脚本的实例
        RScript script = redissonClient.getScript(IntegerCodec.INSTANCE);

        // Lua 脚本 对 KEY[1]+1并返回，第一次设置过期时间 ARGV[1]
        String luaScript =
                "if redis.call('exists', KEYS[1]) == 1 then " +
                        "  return redis.call('incr', KEYS[1]); " +
                        "else " +
                        "  redis.call('set', KEYS[1], 1); " +
                        "  redis.call('expire', KEYS[1], ARGV[1]); " +
                        "  return 1; " +
                        "end";
        Object count = script.eval(
                RScript.Mode.READ_WRITE,
                luaScript,
                RScript.ReturnType.INTEGER,
                Collections.singletonList(redisKey),
                expireTime
        );
        return (long) count;
    }
}

